/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * LiberAcus
 * Copyright (C) 2012 - 2014 Massimiliano Maniscalco <max.maniscalco@gmail.com>
 * 
LiberAcus is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * LiberAcus is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "parser_xml.h"
#include <glibmm/convert.h>
#include <iostream>



#ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
void ParserXML::
on_start_document()
{
	//std::cout << "on_start_document(): inizio file" << std::endl;
}

void ParserXML::
on_end_document()
{
	commit_importing_end.emit();
}

void ParserXML::
on_start_element(const Glib::ustring& name, const AttributeList& attributes)
{
	if ( file_tipo == FILE_TIPO_SCONOSCIUTO )
	{
		if ( name == Glib::ustring ( "LiberAcus" ) )
			file_tipo = FILE_TIPO_DATA;
		else if ( name == Glib::ustring ( "LiberAcus_preferences" ) )
			file_tipo = FILE_TIPO_PREF;
	}
	else if ( file_tipo == FILE_TIPO_PREF )
	{
		if ( name == Glib::ustring ( "intestazione" ) )
		{
			codice_classe = NESSUNA_CLASSE;
			codice_elemento = PREF_INTESTAZIONE;
		}
		else if ( name == Glib::ustring ( "saluto" ) )
		{
			codice_classe = NESSUNA_CLASSE;
			codice_elemento = PREF_SALUTO;
		}
		else if ( name == Glib::ustring ( "eliminazione" ) )
		{
			codice_classe = NESSUNA_CLASSE;
			codice_elemento = PREF_ELIMINAZIONE;
		}
		else if ( name == Glib::ustring ( "azzeramento" ) )
		{
			codice_classe = NESSUNA_CLASSE;
			codice_elemento = PREF_AZZERAMENTO;
		}
		else if ( name == Glib::ustring ( "salvataggio_uscita" ) )
		{
			codice_classe = NESSUNA_CLASSE;
			codice_elemento = PREF_SAVE_USCITA;
		}
		else if ( name == Glib::ustring ( "stampa_numero" ) )
		{
			codice_classe = NESSUNA_CLASSE;
			codice_elemento = PREF_STAMPA_NR;
		}
		else if (name == Glib::ustring ( "visualizza_numero" ))
		{
			codice_classe = NESSUNA_CLASSE;
			codice_elemento = PREF_VISUAL_NR;
		}
	}
	else if ( file_tipo == FILE_TIPO_DATA )
	{
		if ( codice_classe == NESSUNA_CLASSE )
		{
			if ( name == Glib::ustring ( "data_salvataggio" ) )
				codice_elemento = 1;	// data salvataggio
			if ( name == Glib::ustring ( "ultimo_numero" ) )
				codice_elemento = 2;	// ultimo numero emesso
			if ( name == Glib::ustring ( "cliente" ) )
			{
				codice_classe = CLASSE_CLIENTE;
				clnt->clean_up();
			}
			if ( name == Glib::ustring ( "prestazione" ) )
			{
				codice_classe = CLASSE_PRESTAZIONE;
				prest->clean_up();
			}
			if ( name == Glib::ustring ( "ricevuta" ) )
			{
				codice_classe = CLASSE_RICEVUTA;
				ricev->clean_up();
			}
		}
		if ( codice_classe == CLASSE_RICEVUTA_V2 )
		{
			if (name == Glib::ustring ( "numero_capo" ))
			{
				codice_elemento = CAPO_NUMERO;
				capo->clean_up ();
			}
			if (name == Glib::ustring ( "nome_capo" ))
				codice_elemento = CAPO_NOME;
		}
		if ( codice_classe == CLASSE_PRESTAZIONE || codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2 )
		{
			if (name == Glib::ustring ( "capo" ))
			{
				codice_elemento = PREST_CAPO;
				if (codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					prest->clean_up ();
			}
			if (name == Glib::ustring ( "descrizione" ))
				codice_elemento = PREST_DESCRIZIONE;
			if (name == Glib::ustring ( "prezzo" ))
				codice_elemento = PREST_PREZZO;
			if (name == Glib::ustring ( "quantita" ))
				codice_elemento = PREST_QUANTITA;
			if (name == Glib::ustring ( "completata" ))
				codice_elemento = PREST_COMPLETATA;
		}
		if ( codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2 )
		{
			if ( name == Glib::ustring ( "numero" ) )
				codice_elemento = RICEV_NUMERO;
			if ( name == Glib::ustring ( "nome_cliente" ) )
				codice_elemento = RICEV_NOME;
			if ( name == Glib::ustring ( "data_accettazione" ) )
				codice_elemento = RICEV_DATA_ACC;
			if ( name == Glib::ustring ( "ora_accettazione" ) )
				codice_elemento = RICEV_ORA_ACC;
			if ( name == Glib::ustring ( "capi" ) )
				codice_classe = CLASSE_RICEVUTA_V2;
			if ( name == Glib::ustring ( "acconto" ) )
				codice_elemento = RICEV_ACCONTO;
			if ( name == Glib::ustring ( "data_ritiro" ) )
				codice_elemento = RICEV_DATA_RIT;
			if ( name == Glib::ustring ( "ora_ritiro" ) )
				codice_elemento = RICEV_ORA_RIT;
			if ( name == Glib::ustring ( "urgente" ) )
				codice_elemento = RICEV_URGENTE;
			if ( name == Glib::ustring ( "pagato" ) || name == Glib::ustring ( "consegnato" ) )
				codice_elemento = RICEV_CONSEGNATO;
		}
		if ( codice_classe == CLASSE_CLIENTE )
		{
			if ( name == Glib::ustring ( "nome" ) )
				codice_elemento = CLIEN_NOME;
			if ( name == Glib::ustring ( "telefono" ) )
				codice_elemento = CLIEN_TELEFONO;
		}
	}
}

void ParserXML::
on_end_element(const Glib::ustring& name )
{
	if ( file_tipo == FILE_TIPO_PREF )
	{
		if ( name == Glib::ustring ( "LiberAcus_preferences" ) )
		{
			file_tipo = FILE_TIPO_SCONOSCIUTO;
			commit_load_preferenze.emit (preferenze);
		}
	}
	else if ( file_tipo == FILE_TIPO_DATA )
	{
		if ( name == Glib::ustring ( "LiberAcus" ) )
			file_tipo = FILE_TIPO_SCONOSCIUTO;
		if ( name == Glib::ustring ( "ultimo_numero" ) )
			commit_date_file.emit ( data_salvataggio );
		if ( name == Glib::ustring ( "prestazione" ) )
		{
			if ( codice_classe == CLASSE_PRESTAZIONE )
			{
				commit_import_prestazione.emit ( *prest );
				codice_classe = NESSUNA_CLASSE;
			}
			else if ( codice_classe == CLASSE_RICEVUTA )
				ricev->importa_prestazione ( *prest );
			else if ( codice_classe == CLASSE_RICEVUTA_V2 )
				capo->aggiungi_prestazione ( *prest );
		}
		else if ( name == Glib::ustring ( "contenitore_capo" ) )
		{
			if ( codice_classe == CLASSE_RICEVUTA_V2 )
				ricev->aggiungi_capo ( *capo );
		}
		else if ( name == Glib::ustring ( "ricevuta" ) )
		{
			commit_import_ricevuta.emit ( *ricev );
			codice_classe = NESSUNA_CLASSE;
		}
		else if ( name == Glib::ustring ( "cliente" ) )
		{
			commit_import_cliente.emit ( *clnt );
			codice_classe = NESSUNA_CLASSE;
		}
	}
	codice_elemento = 0;
}

void ParserXML::
on_characters(const Glib::ustring& text)
{
	try
	{
		switch ( codice_elemento )
		{
			// classe Preferenze
			case PREF_INTESTAZIONE: // preferenze intestazione
				preferenze.set_intestazione_ricevuta (preferenze.get_intestazione_ricevuta ().append (text));
				break;
			case PREF_SALUTO: // preferenze saluto
				preferenze.set_saluto_ricevuta (preferenze.get_saluto_ricevuta ().append(text));
				break;
			case PREF_ELIMINAZIONE: // preferenze eliminazione
				preferenze.set_eliminazione_ricevute (text);
				break;
			case PREF_AZZERAMENTO: // preferenze azzeramento
				preferenze.set_azzeramento_numero (text);
				break;
			case PREF_SAVE_USCITA: // preferenze salvataggio in uscita
				preferenze.set_salvataggio_automatico (text);
				break;
			case PREF_STAMPA_NR: // preferenze stampa il numero della ricevuta
				preferenze.set_stampa_numero_ricevuta (text);
				break;
			case PREF_VISUAL_NR: // preferenze visualizza il numero della ricevuta
				preferenze.set_visualizza_numero_ricevuta (text);
				break;
			
			case 1: // data salvataggio
				data_ora.tm_year = atoi ( text.substr ( 0, 4 ).c_str() ) - 1900;
				data_ora.tm_mon = atoi ( text.substr ( 5, 2 ).c_str() ) - 1;
				data_ora.tm_mday = atoi ( text.substr ( 8, 2 ).c_str() );
				data_ora.tm_hour = 1;
				data_ora.tm_min = 0;
				data_ora.tm_sec = 0;
				data_salvataggio = mktime(&data_ora);
				break;
			case 2: // ultimo numero emesso
				Ricevuta::set_numero_ricevute_emesse ( atoi( text.c_str() ) );
				break;

			// classe Prestazione
			case PREST_CAPO:
				if (codice_classe == CLASSE_PRESTAZIONE || codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					prest->set_capo ( prest->get_capo().append(text) );
				break;
			case PREST_DESCRIZIONE:
				if (codice_classe == CLASSE_PRESTAZIONE || codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					prest->set_descrizione ( prest->get_descrizione().append(text) );
				break;
			case PREST_PREZZO:
				if (codice_classe == CLASSE_PRESTAZIONE || codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					prest->set_prezzo ( text );
				break;
			case PREST_QUANTITA:
				if (codice_classe == CLASSE_PRESTAZIONE || codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					prest->set_quantita ( text );
				break;
			case PREST_COMPLETATA:
				if (codice_classe == CLASSE_PRESTAZIONE || codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					prest->set_completata ( text );
				break;

			// classe Ricevuta
			case RICEV_NUMERO:
				if ( codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					ricev->set_numero ( atoi( text.c_str() ) );
				break;
			case RICEV_NOME:
				if ( codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					ricev->set_nome_cliente ( ricev->get_nome_cliente ().append( text ) );
				break;
			case RICEV_DATA_ACC:
				data_ora.tm_year = atoi ( text.substr ( 0, 4 ).c_str() ) - 1900;
				data_ora.tm_mon = atoi ( text.substr ( 5, 2 ).c_str() ) - 1;
				data_ora.tm_mday = atoi ( text.substr ( 8, 2 ).c_str() );
				break;
			case RICEV_ORA_ACC:
				data_ora.tm_hour = atoi ( text.substr ( 0, 2 ).c_str() );
				data_ora.tm_min = atoi ( text.substr ( 3, 2 ).c_str() );
				data_ora.tm_sec = atoi ( text.substr ( 6, 2 ).c_str() );
				if ( codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					ricev->set_data_accettazione ( &data_ora );
				break;
			case RICEV_ACCONTO:
				if ( codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					ricev->set_acconto ( text );
				break;
			case RICEV_DATA_RIT:
				data_ora.tm_year = atoi ( text.substr ( 0, 4 ).c_str() ) - 1900;
				data_ora.tm_mon = atoi ( text.substr ( 5, 2 ).c_str() ) - 1;
				data_ora.tm_mday = atoi ( text.substr ( 8, 2 ).c_str() );
				break;
			case RICEV_ORA_RIT:
				data_ora.tm_hour = atoi ( text.substr ( 0, 2 ).c_str() );
				data_ora.tm_min = atoi ( text.substr ( 3, 2 ).c_str() );
				data_ora.tm_sec = atoi ( text.substr ( 6, 2 ).c_str() );
				if ( codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					ricev->set_data_ritiro ( &data_ora );
				break;
			case RICEV_URGENTE:
				if ( codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					ricev->set_urgente ( text );
				break;
			case RICEV_CONSEGNATO:
				if ( codice_classe == CLASSE_RICEVUTA || codice_classe == CLASSE_RICEVUTA_V2)
					ricev->set_consegnato ( text );
				break;

			// classe Capo
			case CAPO_NUMERO:
				if ( codice_classe == CLASSE_RICEVUTA_V2 )
					capo->set_numero ( text );
				break;
			case CAPO_NOME:
				if ( codice_classe == CLASSE_RICEVUTA_V2 )
					capo->set_capo ( capo->get_capo().append( text ));
				break;
				
			// classe Cliente
			case CLIEN_NOME:
				if ( codice_classe == CLASSE_CLIENTE )
					clnt->set_nome ( clnt->get_nome().append( text ) );
				break;
			case CLIEN_TELEFONO:
				if ( codice_classe == CLASSE_CLIENTE )
					clnt->set_telefono ( clnt->get_telefono ().append( text ) );
				break;
		}
	}
	catch(const Glib::ConvertError& ex)
	{
		std::cerr << "ParserXML::on_characters(): Exception caught while converting text for std::cout: " << ex.what() << std::endl;
	}
}

void ParserXML::
on_comment(const Glib::ustring& text)
{
	try
	{
		std::cout << "on_comment(): " << text << std::endl;
	}
	catch(const Glib::ConvertError& ex)
	{
		std::cerr << "ParserXML::on_comment(): Exception caught while converting text for std::cout: " << ex.what() << std::endl;
	}
}

void ParserXML::
on_warning(const Glib::ustring& text)
{
	try
	{
		std::cout << "on_warning(): " << text << std::endl;
	}
	catch(const Glib::ConvertError& ex)
	{
		std::cerr << "ParserXML::on_warning(): Exception caught while converting text for std::cout: " << ex.what() << std::endl;
	}
}

void ParserXML::
on_error(const Glib::ustring& text)
{
	try
	{
		std::cout << "on_error(): " << text << std::endl;
	}
	catch(const Glib::ConvertError& ex)
	{
		std::cerr << "ParserXML::on_error(): Exception caught while converting text for std::cout: " << ex.what() << std::endl;
	}
}

void ParserXML::
on_fatal_error(const Glib::ustring& text)
{
	try
	{
		std::cout << "on_fatal_error(): " << text << std::endl;
	}
	catch(const Glib::ConvertError& ex)
	{
		std::cerr << "ParserXML::on_characters(): Exception caught while converting value for std::cout: " << ex.what() << std::endl;
	}
}

#endif